Skip to content

fix(fuzz): carve out return-value-placement dead stores — closes #112#118

Open
avrabe wants to merge 1 commit into
mainfrom
fix/issue-112-fuzz-harness-return-value-carveout
Open

fix(fuzz): carve out return-value-placement dead stores — closes #112#118
avrabe wants to merge 1 commit into
mainfrom
fix/issue-112-fuzz-harness-return-value-carveout

Conversation

@avrabe
Copy link
Copy Markdown
Contributor

@avrabe avrabe commented May 15, 2026

Summary

Closes #112 — the exploration fuzz harness `i64_lowering_doesnt_clobber_params` was false-positiving on the `Movw R0, 0; Mov R0, R8` return-value-placement pair. The Movw zeros R0 and is then immediately overwritten by the Mov — a redundant dead store, not a real AAPCS clobber. The param IS already preserved at that point in the function.

This is the option (b) harness-side fix per the issue's investigation comment, deliberately cheaper than the underlying codegen peephole (option a, deferred to a future codegen-quality PR).

Carve-out

For each ARM instruction in the param-protection window, check the immediately-following instruction: if it also writes the same param reg, the current write is provably dead and gets skipped. Indexed iteration via `arm_instrs.get(instr_idx + 1)` keeps the lookup O(1) and side-steps the prior `std::ptr::eq` hack-shape.

Soundness

The carve-out is local — it only suppresses writes whose result is provably dead at the next instruction. A real mid-computation clobber would either:

  • have a non-overwriting next-op → still flagged.
  • be part of a chain where the final write overwrites R{p} → still flagged on the final write (its next op is typically Pop, which doesn't write the param reg).

So the carve-out does not hide real AAPCS clobbers; it only suppresses the duplicate report on the first write of a write-then-overwrite pair.

What this enables

Once green for a couple of fuzz-smoke cycles, this harness can be promoted from `gating: false` to `gating: true` in `.github/workflows/fuzz-smoke.yml` — tracked as a follow-up.

Test plan

  • CI green
  • Fuzz-smoke `i64_lowering_doesnt_clobber_params` no longer reports on the `Movw R0, 0; Mov R0, _` pattern
  • No regression in the LocalSet/LocalTee carve-out path (existing logic preserved verbatim)

Refs: #112 (will be auto-closed by this PR's merge).

🤖 Generated with Claude Code

The exploration fuzz harness `i64_lowering_doesnt_clobber_params` was
flagging `Movw R0, 0` writes as AAPCS param-clobber bugs when the very
next ARM op was a `Mov R0, _` overwriting the same register. The two-
instruction sequence appears in the function-final i32 return-value
placement — the selector zeros R0 and then immediately overwrites with
the actual return value. The Movw R0, 0 is a redundant dead store, not a
real clobber: the param is already preserved at this point and the
immediately-following Mov overrides the zero before any observer sees it.

This is the "option (b) harness-side" fix per the issue's investigation
comment — cheaper than the underlying peephole (option a, deferred for a
future codegen-quality PR) and lets the exploration harness make
forward progress toward gating-status promotion (#31).

## Carve-out shape

For each ARM instruction in the param-protection window, check whether
the immediately-following instruction also writes the same param reg.
If so, the current write is dead and gets skipped. Indexed iteration
keeps the lookup O(1).

## Soundness

The carve-out is local: it only suppresses writes whose result is
*provably* dead at the next instruction. A real mid-computation clobber
would either:
  (a) have non-overwriting next-op → still flagged.
  (b) be part of a chain where the *final* write overwrites R{p} →
      still flagged on the final write (its next op is typically Pop,
      which doesn't write the param reg).

So the carve-out does not hide real AAPCS clobbers; it only suppresses
the duplicate report on the first write of a write-then-overwrite pair.

## What this enables

After this lands and a couple of green fuzz-smoke cycles confirm the
harness stays quiet, it can be promoted from `gating: false` to
`gating: true` in `.github/workflows/fuzz-smoke.yml` — tracked as
task #31.

Issue: #112
@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

i64-extend chain + Movw R0 clobbers param R0 (fuzz, post-#111)

1 participant